import { All, Inject, Injectable, forwardRef } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { BudgetService } from 'src/budget/budget.service'
import { Allocate } from 'src/entity/Allocate'
import { Asset } from 'src/entity/Asset'
import { Borrow } from 'src/entity/Borrow'
import { Budget } from 'src/entity/Budget'
import { Easter } from 'src/entity/Easter'
import { InStore } from 'src/entity/InStore'
import { Purchase } from 'src/entity/Purchase'
import { Receive } from 'src/entity/Receive'
import { Scrap } from 'src/entity/Scrap'
import { Task } from 'src/entity/Task'
import { PurchaseService } from 'src/purchase/purchase.service'
import { Connection, IsNull, Repository } from 'typeorm'

@Injectable()
export class TaskService {
  constructor(
    @InjectRepository(Task)
    private taskRepository: Repository<Task>,
    @Inject(forwardRef(() => BudgetService))
    private readonly budgetService: BudgetService,
    @Inject(forwardRef(() => PurchaseService))
    private readonly purchaseService: PurchaseService,
    private connection: Connection,
  ) { }

  async add(data) {
    await this.taskRepository.save(data)
    return data
  }

  async del(id: number) {
    return await this.taskRepository.update(
      {
        id: id,
      },
      {
        isDelete: true,
      },
    )
  }

  async delByCode(code: string) {
    return await this.taskRepository.update(
      {
        receiveCode: code,
      },
      {
        isDelete: true,
      },
    )
  }

  async update(
    data: Task & {
      assetCode?: string
      isInAllocate?: boolean
      isInBorrow?: boolean
      getDate?: string
    },
  ) {
    const taskData = { ...data }
    if (taskData.assetCode !== null || taskData.assetCode !== undefined) {
      delete taskData.assetCode
    }
    if (taskData.isInAllocate !== null || taskData.isInAllocate !== undefined) {
      delete taskData.isInAllocate
    }
    if (taskData.isInBorrow !== null || taskData.isInBorrow !== undefined) {
      delete taskData.isInBorrow
    }
    if (taskData.getDate !== null || taskData.getDate !== undefined) {
      delete taskData.getDate
    }
    await this.connection.transaction(async (manager) => {
      await this.taskRepository.update(
        {
          id: data.id,
        },
        taskData,
      )
      if (data.taskType === '0') {
        await this.budgetService.updateProperty(
          data.receiveCode,
          'receiveType',
          data.taskStatus,
        )
        await this.budgetService.updateProperty(
          data.receiveCode,
          'reason',
          data.reason,
        )
      }
      // 采购
      if (data.taskType === '1') {
        await this.purchaseService.updateProperty(
          data.receiveCode,
          'purchaseStatus',
          data.taskStatus,
        )
        const purchaseSqlData = await manager.findOne(Purchase, {
          where: {
            purchaseCode: data.receiveCode,
          },
        })
        if (data.taskStatus === '2') {
          // 消耗预算
          await manager.update(
            Budget,
            {
              id: purchaseSqlData.budgetId,
            },
            {
              isUse: true,
            },
          )
        }
        await this.purchaseService.updateProperty(
          data.receiveCode,
          'reason',
          data.reason,
        )
      }
      // 领用
      if (data.taskType === '2') {
        await manager.update(
          Receive,
          {
            receiveCode: data.receiveCode,
          },
          {
            receiveType: data.taskStatus,
            reason: data.reason,
            assetCode: data.assetCode,
            getDate: data.getDate,
          },
        )
        await manager.update(
          Asset,
          {
            assetCode: data.assetCode,
          },
          {
            user: data.receivePerson,
            userId: data.receivePersonId,
            branchId: data.receiveBranchId,
            branchName: data.receiveBranch,
            assetStatus: '2',
          },
        )
      }
      // 借用
      if (data.taskType === '3') {
        await manager.update(
          Borrow,
          {
            borrowCode: data.receiveCode,
          },
          data.isInBorrow
            ? {
              borrowInStatus: data.taskInStatus,
              inReason: data.inReason,
            }
            : {
              borrowOutStatus: data.taskOutStatus,
              outReason: data.outReason,
            },
        )
      }
      // 报废
      if (data.taskType === '5') {
        await manager.update(
          Scrap,
          {
            scrapCode: data.receiveCode,
          },
          {
            scrapType: data.taskStatus,
            reason: data.reason,
          },
        )
        const scrapSqlData = await manager.findOne(Scrap, {
          where: {
            scrapCode: data.receiveCode,
          },
        })
        // 同意则报废资产
        if (data.taskStatus === '2') {
          await manager.update(
            Asset,
            {
              assetCode: scrapSqlData.assetCode,
            },
            {
              assetStatus: '5',
              isDelete: true,
            },
          )
        }
      }
      // 调拨
      if (data.taskType === '6') {
        await manager.update(
          Allocate,
          {
            allocateCode: data.receiveCode,
          },
          data.isInAllocate
            ? {
              allocateInStatus: data.taskInStatus,
              inReason: data.inReason,
            }
            : {
              allocateOutStatus: data.taskOutStatus,
              outReason: data.outReason,
            },
        )
        const allocateSqlData = await manager.findOne(Allocate, {
          where: {
            allocateCode: data.receiveCode,
          },
        })
        // 如果都同意了
        if (data.taskInStatus === '2' && data.taskOutStatus === '2') {
          // 更新资产所属仓库
          const asset = await manager.update(
            Asset,
            {
              assetCode: allocateSqlData.assetCode,
            },
            {
              branchId: allocateSqlData.allocateInBranchId,
              branchName: allocateSqlData.allocateInBranch,
              warehouseId: allocateSqlData.warehouseId,
            },
          )
          const assetSqlData = await manager.findOne(Asset, {
            where: {
              assetCode: allocateSqlData.assetCode,
            },
          })

          // 新增调拨入库
          await manager.insert(InStore, {
            inStoreName: allocateSqlData.allocateName,
            inStoreType: '3',
            inStoreDate:
              data.taskInDate > data.taskOutDate
                ? data.taskInDate
                : data.taskOutDate,
            inStoreNumber: 1,
            assetIds: assetSqlData.id.toString(),
            branchName: allocateSqlData.allocateInBranch,
            branchId: allocateSqlData.allocateInBranchId,
            remark: allocateSqlData.remark,
          })
        }
      }
      // 资产复活
      if (data.taskType === '7') {
        await manager.update(
          Easter,
          {
            easterCode: data.receiveCode,
          },
          {
            easterType: data.taskStatus,
            reason: data.reason,
          },
        )
        const easterSqlData = await manager.findOne(Easter, {
          where: {
            easterCode: data.receiveCode,
          },
        })
        // 同意则复活资产
        if (data.taskStatus === '2') {
          await manager.update(
            Asset,
            {
              assetCode: easterSqlData.assetCode,
            },
            {
              assetStatus: '1',
              isDelete: null,
            },
          )
        }
      }
    })
    return {}
  }

  // 分页查询
  async getPageList({
    pageRequest: { pageIndex, pageSize },
    taskName,
    taskType,
    receivePerson,
    receiveBranch,
    taskStatus,
    taskInStatus,
    taskOutStatus,
    orgId,
  }) {
    const sqlAllData = await this.taskRepository.find({
      where: [
        {
          isDelete: IsNull(),
          receiveBranchId: orgId,
          taskName: taskName,
          taskType: taskType,
          receivePerson: receivePerson,
          receiveBranch: receiveBranch,
          taskStatus: taskStatus,
          taskInStatus: taskInStatus,
          taskOutStatus: taskOutStatus,
        },
        {
          isDelete: IsNull(),
          receiveOutBranchId: orgId,
          taskName: taskName,
          taskType: taskType,
          receivePerson: receivePerson,
          receiveBranch: receiveBranch,
          taskStatus: taskStatus,
          taskInStatus: taskInStatus,
          taskOutStatus: taskOutStatus,
        },
      ],
    })
    const sqlData = await this.taskRepository.find({
      where: [
        {
          isDelete: IsNull(),
          receiveBranchId: orgId,
          taskName: taskName,
          taskType: taskType,
          receivePerson: receivePerson,
          receiveBranch: receiveBranch,
          taskStatus: taskStatus,
          taskInStatus: taskInStatus,
          taskOutStatus: taskOutStatus,
        },
        {
          isDelete: IsNull(),
          receiveOutBranchId: orgId,
          taskName: taskName,
          taskType: taskType,
          receivePerson: receivePerson,
          receiveBranch: receiveBranch,
          taskStatus: taskStatus,
          taskInStatus: taskInStatus,
          taskOutStatus: taskOutStatus,
        },
      ],
      skip: (pageIndex - 1) * pageSize,
      take: pageSize,
      withDeleted: false,
    })

    return {
      content: sqlData,
      total: sqlAllData.length,
    }
  }

  // 获取详情
  async getDetail({ type, code }) {
    let sqlData
    await this.connection.transaction(async (manager) => {
      // 预算
      if (type === '0') {
        sqlData = await this.budgetService.getDetailByCode(code)
      }
      // 采购
      if (type === '1') {
        sqlData = await this.purchaseService.getDetailByCode(code)
      }
      // 领用
      if (type === '2') {
        const receiveSqlData = await manager.findOne(Receive, {
          where: {
            receiveCode: code,
            isDelete: IsNull(),
          },
        })
        sqlData = {
          ...receiveSqlData,
          typeId: receiveSqlData.typeId.toString(),
        }
      }
      // 借用
      if (type === '3') {
        const borrowSqlData = await manager.findOne(Borrow, {
          where: {
            borrowCode: code,
            isDelete: IsNull(),
          },
        })
        const assetSqlData = await manager.findOne(Asset, {
          where: {
            assetCode: borrowSqlData.assetCode,
          },
        })
        sqlData = {
          ...borrowSqlData,
          assetCode: assetSqlData.assetCode,
          assetName: assetSqlData.assetName,
          typeId: assetSqlData.typeId.toString(),
        }
      }
      // 报废
      if (type === '5') {
        const scrapSqlData = await manager.findOne(Scrap, {
          where: {
            scrapCode: code,
            isDelete: IsNull(),
          },
        })
        sqlData = {
          ...scrapSqlData,
          scrapTypeId: scrapSqlData.scrapTypeId.toString(),
        }
      }
      // 调拨
      if (type === '6') {
        const allocateSqlData = await manager.findOne(Allocate, {
          where: {
            allocateCode: code,
            isDelete: IsNull(),
          },
        })
        const assetSqlData = await manager.findOne(Asset, {
          where: {
            assetCode: allocateSqlData.assetCode,
          },
        })
        sqlData = {
          ...allocateSqlData,
          assetCode: assetSqlData.assetCode,
          assetName: assetSqlData.assetName,
          typeId: assetSqlData.typeId.toString(),
          warehouseId: allocateSqlData.warehouseId.toString(),
        }
      }
      // 资产复活
      if (type === '7') {
        const easterSqlData = await manager.findOne(Easter, {
          where: {
            easterCode: code,
            isDelete: IsNull(),
          },
        })
        sqlData = {
          ...easterSqlData,
          easterTypeId: easterSqlData.easterTypeId.toString(),
        }
      }
    })
    return sqlData
  }

  // 更新某个属性
  async updateProperty(code, property, value) {
    return await this.taskRepository.update(
      {
        receiveCode: code,
      },
      {
        [property]: value,
      },
    )
  }

  // 获取可领用资产列表
  async getReceiveAssetList({ isUserId = false, typeId, orgId }) {
    // isUserId userId为空表示没有使用人
    let result
    await this.connection.transaction(async (manager) => {
      const sqlData = await manager.find(Asset, {
        where: isUserId
          ? {
            userId: IsNull(),
            isDelete: IsNull(),
            branchId: orgId,
            typeId: typeId,
          }
          : {
            isDelete: IsNull(),
            branchId: orgId,
            typeId: typeId,
          },
      })
      result = sqlData.map((item) => {
        return {
          label: item.assetName,
          value: item.assetCode,
        }
      })
    })
    return result
  }
}
